﻿namespace CacheProvider
{
    #region N A M E S P A C E   I M P O R T S

    using System;
    using System.Collections.Generic;
    using System.Configuration.Provider;
    using System.Diagnostics;
    using System.Web.Configuration;
    using CacheProviderEntities;
    using Microsoft.Practices.Composite.Presentation.Events;

    #endregion

    public static class CacheBroker
    {

        #region P U B L I C   E V E N T S

        /// <summary>
        /// Subscribe to this event to get notifications about any errors encountered
        /// by the Cache Provider.  Subscribe only once per AppDomain.
        /// </summary>
        public static event EventHandler<CacheProviderErrorEventArgs> CacheProviderErrorEvent;

        #endregion

        #region P R I V A T E   A T T R I B U T E S

        private static CacheProvider _providerInstance;
        private static CacheProviderCollection _providersCollection;
        private static readonly object Serializer = new object();

        #endregion

        #region P R I V A T E   M E T H O D S

        /// <summary>
        /// This function loads providers from the App.Config or Web.config file
        /// </summary>
        private static bool EnsureProviderIsLoaded()
        {
            var providerLoaded = false;
            // Avoid claiming lock if provider already loaded
            if (_providerInstance == null)
            {
                lock (Serializer)
                {
                    //make sure _provider is still null
                    if (_providerInstance == null)
                    {
                        //Get a reference to the <cacheProvider> section 
                        var cacheProviderSection = (CacheProviderSection)
                            WebConfigurationManager.GetSection("cacheProvider");

                        if (cacheProviderSection != null && cacheProviderSection.Enabled)
                        {
                            //Load registered providers and point _providerInstance to the default provider
                            _providersCollection = new CacheProviderCollection();

                            ProvidersHelper.InstantiateProviders
                                (cacheProviderSection.Providers, _providersCollection, typeof(CacheProvider));

                            if (_providersCollection.Count > 0)
                            {
                                //Get The Default Provider from the Providers collection
                                _providerInstance = _providersCollection[cacheProviderSection.DefaultProvider];

                                if (_providerInstance == null)
                                {
                                    var errorMessage = string.Format("Unable To Load Default Cache Provider [{0}]",
                                                                     cacheProviderSection.DefaultProvider);
                                    throw new ProviderException(errorMessage);
                                }
                                else
                                {
                                    //creating performance counter categories
                                    //_providerInstance.CheckPerformanceCounterCategories();
                                }

                                //Subscribe to the Error Event of the Cache Provider.
                                _providerInstance.EventAggregatorInstance.GetEvent<CacheProviderErrorEvent>().Subscribe(Process_ProviderError);

                                providerLoaded = true;
                            }
                        }
                    }
                    else
                        providerLoaded = true;
                }
            }
            else
                providerLoaded = true;

            return providerLoaded;
        }

        private static void Process_ProviderError(CacheProviderErrorEventArgs cacheProviderErrorEventArgs)
        {
            if (_providerInstance != null && _providerInstance.LogWriter != null)
            {
                var message = string.Format("Cache with key {0} is having error:{1}",
                                            cacheProviderErrorEventArgs.CacheKey,
                                            cacheProviderErrorEventArgs.ErrorMessage);

                _providerInstance.LogWriter.Write(message, "TomcatLogging", 1, (int)CacheOperation.Error, TraceEventType.Error,
                                                 cacheProviderErrorEventArgs.CacheKey);
            }
            if (CacheProviderErrorEvent != null)
                CacheProviderErrorEvent(cacheProviderErrorEventArgs.Sender, cacheProviderErrorEventArgs);
        }

        #endregion

        #region C A C H E P R O V I D E R   W R A P P E R   M E M B E R S

        #region P R O P E R T I E S

        /// <summary>
        /// Whether Tags are supported by the configured Cache Provider.
        /// </summary>
        public static bool IsCacheTagSupported
        {
            get
            {
                var result = false;
                if (EnsureProviderIsLoaded())
                    result = _providerInstance.IsCacheTagSupported;
                return result;
            }
        }

        /// <summary>
        /// Whether Locking is supported by the configured Cache Provider.
        /// </summary>
        public static bool IsConcurrencySupported
        {
            get
            {
                var result = false;
                if (EnsureProviderIsLoaded())
                    result = _providerInstance.IsConcurrencySupported;

                return result;
            }
        }

        /// <summary>
        /// Whether Regions are supported by the configured Cache Provider.
        /// </summary>
        public static bool IsRegionSupported
        {
            get
            {
                var result = false;
                if (EnsureProviderIsLoaded())
                    result = _providerInstance.IsRegionSupported;

                return result;
            }
        }

        /// <summary>
        /// Default Time-To-Live value for the Cache Entries in Milliseconds.
        /// </summary>
        public static long DefaultExpirationTimeInMilliSeconds
        {
            get
            {
                var result = default(long);
                if (EnsureProviderIsLoaded())
                    result = _providerInstance.DefaultExpirationTimeInMilliSeconds;
                return result;
            }
            set
            {
                if (EnsureProviderIsLoaded())
                    _providerInstance.DefaultExpirationTimeInMilliSeconds = value;
            }
        }

        /// <summary>
        /// Whether Named Cache is supported by the configured Cache Provider.
        /// </summary>
        public static bool IsNamedCacheSupported
        {
            get
            {
                var result = false;
                if (EnsureProviderIsLoaded())
                    result = _providerInstance.IsNamedCacheSupported;

                return result;
            }
        }

        /// <summary>
        /// Actual provider instance.
        /// </summary>
        public static CacheProvider Provider
        {
            get
            {
                CacheProvider result = null;
                if (EnsureProviderIsLoaded())
                    result = _providerInstance;

                return result;
            }
        }

        #endregion

        #region A D D   O V E R L O A D S

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        /// <remarks>Can throw exception depending on the provider if the key already exist.</remarks>
        public static bool Add(string key, object value, TimeSpan timeout, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, timeout, regionName);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="ttlInMilliSeconds">Time-to-Live in milliseconds for this entry in Cache.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, long ttlInMilliSeconds)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, ttlInMilliSeconds);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="useDefaultExpiration">Uses the default expiration value set either through Provider configuration or Provider's default value <see cref="DefaultExpirationTimeInMilliSeconds"/></param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, bool useDefaultExpiration)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, useDefaultExpiration);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, IEnumerable<string> cacheTags)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, cacheTags);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, IEnumerable<string> cacheTags, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, TimeSpan timeout, IEnumerable<string> cacheTags)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, timeout, cacheTags);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, TimeSpan timeout, IEnumerable<string> cacheTags, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, timeout, cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, regionName);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value, TimeSpan timeout)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value, timeout);

            return result;
        }

        /// <summary>
        /// Adds an object to the cache.
        /// If an item using the same key is already present in the cache, this call either 
        /// throws an exception or returns false depending on the provider.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <returns>True if successful else false.</returns>
        public static bool Add(string key, object value)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Add(key, value);

            return result;
        }

        #endregion

        #region G E T   O V E R L O A D S

        /// <summary>
        /// Returns cache entries for an array of keys at a time.
        /// </summary>
        /// <param name="keys">variable number of keys for which to get cache entries</param>
        /// <returns>An instance of <see cref="IDictionary{TKey,TValue}" with the entries from Cache as dictionary values./></returns>
        public static IDictionary<string, object> Get(params string[] keys)
        {
            IDictionary<string, object> result = null;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Get(keys);

            return result;
        }

        /// <summary>
        /// Gets a cache entry matching with the key in a strongly-typed manner.
        /// </summary>
        /// <typeparam name="T">Type of Cache Entry Value</typeparam>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <returns>An Instance of T if the entry is found, else null.</returns>
        public static T Get<T>(string key)
        {
            var result = default(T);
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Get<T>(key);

            return result;
        }

        /// <summary>
        /// Gets a cache entry matching with the key.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <returns>An <see cref="object" instance with the Cache Value corresponding to the entry if found, else null/></returns>
        public static object Get(string key)
        {
            object result = null;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Get(key);
            return result;
        }

        /// <summary>
        /// Gets a cache entry matching with the key and region name.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="regionName">Name of the region where the key\value is stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Use other overloads if not required or not supported.</param>
        /// <returns>An <see cref="object" instance with the Cache Value corresponding to the entry if found, else null</returns>
        public static object Get(string key, string regionName)
        {
            object result = null;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Get(key, regionName);
            return result;
        }

        /// <summary>
        /// Gets and locks a cache entry matching with the agruments passed.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="timeout">Time for which the key is locked.</param>
        /// <param name="lockId">Returns Identifier of the lock so that the same can be used to unlock</param>
        /// <param name="regionName">Name of the region where the key\value is stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Use other overloads if not required or not supported.</param>
        /// <returns>An <see cref="object" instance with the Cache Value corresponding to the entry if found, else null</returns>
        /// <remarks>Locking behavior may be different for different providers. See provider API for details.</remarks>
        public static object GetAndLock(string key, TimeSpan timeout, out Guid lockId, string regionName)
        {
            object result = null;
            lockId = Guid.Empty;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetAndLock(key, timeout, out lockId, regionName);

            return result;
        }

        /// <summary>
        /// Gets and locks a cache entry matching with the agruments passed.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="timeout">Time for which the key is locked.</param>
        /// <param name="lockId">Returns Identifier of the lock so that the same can be used to unlock</param>
        /// <param name="regionName">Name of the region where the key\value is stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Use other overloads if not required or not supported.</param>
        /// <param name="forceLock">If forceLock is true, key is locked irrespective of key-value pair presence in cache</param>
        /// <returns>An <see cref="object" instance with the Cache Value corresponding to the entry if found, else null</returns>
        /// <remarks>Locking behavior may be different for different providers. See provider API for details.</remarks>
        public static object GetAndLock(string key, TimeSpan timeout, out Guid lockId, string regionName, bool forceLock)
        {
            object result = null;
            lockId = Guid.Empty;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetAndLock(key, timeout, out lockId, regionName, forceLock);

            return result;
        }

        /// <summary>
        /// Gets and locks a cache entry matching with the agruments passed.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="timeout">Time for which the key is locked.</param>
        /// <param name="lockId">Returns Identifier of the lock so that the same can be used to unlock</param>
        /// <returns>An <see cref="object" instance with the Cache Value corresponding to the entry if found, else null</returns>
        /// <remarks>Locking behavior may be different for different providers. See provider API for details.</remarks>
        public static object GetAndLock(string key, TimeSpan timeout, out Guid lockId)
        {
            object result = null;
            lockId = Guid.Empty;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetAndLock(key, timeout, out lockId);

            return result;
        }

        /// <summary>
        /// Gets and locks a cache entry matching with the agruments passed.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="timeout">Time for which the key is locked.</param>
        /// <param name="lockId">Returns Identifier of the lock so that the same can be used to unlock</param>
        /// <param name="forceLock">If forceLock is true, key is locked irrespective of key-value pair presence in cache</param>
        /// <returns>An <see cref="object" instance with the Cache Value corresponding to the entry if found, else null</returns>
        /// <remarks>Locking behavior may be different for different providers. See provider API for details.</remarks>
        public static object GetAndLock(string key, TimeSpan timeout, out Guid lockId, bool forceLock)
        {
            object result = null;
            lockId = Guid.Empty;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetAndLock(key, timeout, out lockId, forceLock);

            return result;
        }

        /// <summary>
        /// Gets all Cache entries matching with all the tags provided.
        /// </summary>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/></param>
        /// <param name="regionName">Name of the region where the key\value is stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Use other overloads if not required or not supported.</param>
        /// <returns>An <see cref="IEnumerable{KeyValuePair<string,object>}" where each key value pair is a cache key and its value./> </returns>
        public static IEnumerable<KeyValuePair<string, object>> GetObjectsByAllTags(IEnumerable<string> cacheTags, string regionName)
        {
            IEnumerable<KeyValuePair<string, object>> result = null;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetObjectsByAllTags(cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Gets all Cache entries matching with any of the tags provided.
        /// </summary>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/></param>
        /// <param name="regionName">Name of the region where the key\value is stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Use other overloads if not required or not supported.</param>
        /// <returns>An <see cref="IEnumerable{KeyValuePair<string,object>}" where each key value pair is a cache key and its value./> </returns>
        public static IEnumerable<KeyValuePair<string, object>> GetObjectsByAnyTag(IEnumerable<string> cacheTags, string regionName)
        {
            IEnumerable<KeyValuePair<string, object>> result = null;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetObjectsByAnyTag(cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Gets all Cache entries matching with the tag provided.
        /// </summary>
        /// <param name="cacheTag">Tag associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/></param>
        /// <param name="regionName">Name of the region where the key\value is stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Use other overloads if not required or not supported.</param>
        /// <returns>An <see cref="IEnumerable{KeyValuePair<string,object>}" where each key value pair is a cache key and its value./> </returns>
        public static IEnumerable<KeyValuePair<string, object>> GetObjectsByTag(string cacheTag, string regionName)
        {
            IEnumerable<KeyValuePair<string, object>> result = null;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetObjectsByTag(cacheTag, regionName);

            return result;
        }

        /// <summary>
        /// Gets all the objects stored in a region.
        /// </summary>
        /// <param name="regionName">Name of the region where the key\value is stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Use other overloads if not required or not supported.</param>
        /// <returns>An <see cref="IEnumerable{KeyValuePair<string,object>}" where each key value pair is a cache key and its value./> </returns>
        public static IEnumerable<KeyValuePair<string, object>> GetObjectsInRegion(string regionName)
        {
            IEnumerable<KeyValuePair<string, object>> result = null;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetObjectsInRegion(regionName);

            return result;
        }

        /// <summary>
        /// Gets the region name for a cache key if Regions are supported by the provider. <seealso cref="IsRegionSupported"/> 
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <returns>name of the reqion</returns>
        public static string GetSystemRegionName(string key)
        {
            string result = null;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetSystemRegionName(key);

            return result;
        }


        /// <summary>
        /// Returns an <see cref="IEnumerable{T}"/> containing all the regions if Regions are supported by 
        /// the provider. <seealso cref="IsRegionSupported"/> 
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<string> GetSystemRegions()
        {
            IEnumerable<string> result = null;

            if (EnsureProviderIsLoaded())
                result = _providerInstance.GetSystemRegions();

            return result;
        }

        #endregion

        #region P U T   O V E R L O A D S

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <returns></returns>
        public static bool Put(string key, object value, IEnumerable<string> cacheTags)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, cacheTags);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="dependencyInfo">An instance of <see cref="DependencyInfo"/> </param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, DependencyInfo dependencyInfo, TimeSpan timeout)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, dependencyInfo, timeout);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <param name="dependencyInfo">An instance of <see cref="DependencyInfo"/> </param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, Object value, string regionName, DependencyInfo dependencyInfo)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, regionName, dependencyInfo);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <param name="dependencyInfo">An instance of <see cref="DependencyInfo"/> </param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, Object value, string regionName, DependencyInfo dependencyInfo, TimeSpan timeout)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, regionName, dependencyInfo, timeout);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="useDefaultTimeout">Uses the Default Timeout configured for the provider.  Must be set to true for this overload. </param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, bool useDefaultTimeout)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, useDefaultTimeout);

            return result;
        }


        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="dependencyInfo">An instance of <see cref="DependencyInfo"/></param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, DependencyInfo dependencyInfo)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, dependencyInfo);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, TimeSpan timeout, IEnumerable<string> cacheTags)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, timeout, cacheTags);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, TimeSpan timeout, IEnumerable<string> cacheTags, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, timeout, cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, IEnumerable<string> cacheTags, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, TimeSpan timeout, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, timeout, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put(string key, object value, TimeSpan timeout)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, timeout);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId, TimeSpan timeout)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId, timeout);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId, IEnumerable<string> cacheTags, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId, cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId, TimeSpan timeout, IEnumerable<string> cacheTags, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId, timeout, cacheTags, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId, TimeSpan timeout, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId, timeout, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId, TimeSpan timeout, IEnumerable<string> cacheTags)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId, timeout, cacheTags);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId, regionName);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool PutAndUnlock(string key, object value, Guid lockId, IEnumerable<string> cacheTags)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.PutAndUnlock(key, value, lockId, cacheTags);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <typeparam name="T">Type of Dependency callback payload</typeparam>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <param name="timeout">Time-to-Live for this entry in Cache.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="dependencyInfo">An instance of <see cref="DependencyInfo"/> </param>
        /// <param name="cacheUpdationCallback">Delegate to the method which will be invoked if the dependency changes.</param>
        /// <param name="callbackState">Instance of T that will be passed as parameter to the callback.</param>
        /// <param name="threadOption">Thread on which the callback will be invoked. <see cref="ThreadOption"/></param>
        /// <param name="keepSubscriberReferenceAlive">Whether to hold a weak or a strong reference to the callback.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put<T>(string key, Object value, string regionName, TimeSpan timeout,
                                  IEnumerable<String> cacheTags, DependencyInfo dependencyInfo,
                                  Action<T> cacheUpdationCallback, T callbackState, ThreadOption threadOption,
                                  bool keepSubscriberReferenceAlive)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, regionName, timeout, cacheTags, dependencyInfo, cacheUpdationCallback,
                                            callbackState, threadOption, keepSubscriberReferenceAlive);

            return result;
        }

        /// <summary>
        /// Adds or updates a cache entry.
        /// </summary>
        /// <typeparam name="T">Type of Dependency callback payload</typeparam>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="value">Value associated with the key.  Should be annotated with <see cref="SerializableAttribute"/></param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <param name="useDefaultTimeout">Uses Default Timeout configured for the Provider in configuration for the TTL value.</param>
        /// <param name="cacheTags">Tags associated with the cache if supported by the provider. <seealso cref="IsCacheTagSupported"/> Pass null if not required or not supported.</param>
        /// <param name="dependencyInfo">An instance of <see cref="DependencyInfo"/> </param>
        /// <param name="cacheUpdationCallback">Delegate to the method which will be invoked if the dependency changes.</param>
        /// <param name="callbackState">Instance of T that will be passed as parameter to the callback.</param>
        /// <param name="threadOption">Thread on which the callback will be invoked. <see cref="ThreadOption"/></param>
        /// <param name="keepSubscriberReferenceAlive">Whether to hold a weak or a strong reference to the callback.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Put<T>(string key, Object value, string regionName, bool useDefaultTimeout, IEnumerable<String> cacheTags,
                        DependencyInfo dependencyInfo, Action<T> cacheUpdationCallback, T callbackState,
                        ThreadOption threadOption, bool keepSubscriberReferenceAlive)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Put(key, value, regionName, useDefaultTimeout, cacheTags, dependencyInfo, cacheUpdationCallback,
                                            callbackState, threadOption, keepSubscriberReferenceAlive);

            return result;
        }



        #endregion

        #region R E M O V E   O V E R L O A D S

        /// <summary>
        /// Removes an entry that is locked.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Remove(string key, Guid lockId)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Remove(key, lockId);

            return result;
        }

        /// <summary>
        /// Removes an entry that is locked.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="lockId">Identifier of the lock that was returned when the object was locked.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Remove(string key, Guid lockId, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Remove(key, lockId, regionName);

            return result;
        }

        /// <summary>
        /// Removes an entry from the Cache store.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <returns>True if successful else false.</returns>
        public static bool Remove(string key)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Remove(key);

            return result;
        }

        /// <summary>
        /// Removes an entry from the Cache store.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/></param>
        /// <returns>True if successful else false.</returns>
        public static bool Remove(string key, string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.Remove(key, regionName);

            return result;
        }

        /// <summary>
        /// Removes all entries from the default Cache store.
        /// </summary>
        public static void RemoveAll()
        {
            if (EnsureProviderIsLoaded())
                _providerInstance.RemoveAll();
        }

        /// <summary>
        /// Removes a region.
        /// </summary>
        /// <param name="regionName">Name of the region if supported by the provider. <seealso cref="IsRegionSupported"/></param>
        /// <returns>True if successful else false.</returns>
        public static bool RemoveRegion(string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.RemoveRegion(regionName);

            return result;
        }
        #endregion

        /// <summary>
        /// Resets the expiry an entry in Cache.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="newTimeout">New Time-to-Live value as <see cref="TimeSpan"/> </param>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/>  Pass null if not required or not supported.</param>
        public static void ResetObjectTimeout(string key, TimeSpan newTimeout, string regionName)
        {
            if (EnsureProviderIsLoaded())
                _providerInstance.ResetObjectTimeout(key, newTimeout, regionName);
        }

        /// <summary>
        /// Resets the expiry an entry in Cache.
        /// </summary>
        /// <param name="key">Unique string to identify this entry in Cache.</param>
        /// <param name="newTimeout">New Time-to-Live value as <see cref="TimeSpan"/> </param>
        public static void ResetObjectTimeout(string key, TimeSpan newTimeout)
        {
            if (EnsureProviderIsLoaded())
                _providerInstance.ResetObjectTimeout(key, newTimeout);
        }

        /// <summary>
        /// Removes all the cache entries from a region.
        /// </summary>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/> </param>
        /// <returns>True if successful else false.</returns>
        public static bool ClearRegion(string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.ClearRegion(regionName);

            return result;
        }

        /// <summary>
        /// Create a new region.
        /// </summary>
        /// <param name="regionName">Name of the region where the key\value will be stored if supported by the provider. <seealso cref="IsRegionSupported"/> </param>
        /// <returns>True if successful else false.</returns>
        public static bool CreateRegion(string regionName)
        {
            var result = false;
            if (EnsureProviderIsLoaded())
                result = _providerInstance.CreateRegion(regionName);

            return result;
        }

        /// <summary>
        /// Sets a Named Cache if supported by the provider.  <seealso cref="IsNamedCacheSupported"/>
        /// After calling this method, all operations are performed on set NamedCache in that thread till <see cref="SetDefaultCache()"/> is called.
        /// Use <see cref="SetDefaultCache()"/> in a finally block to set the default Named Cache after
        /// the named cache scope finishes.
        /// </summary>
        /// <param name="cacheName">Named Cache value</param>
        public static void SetNamedCache(string cacheName)
        {
            if (EnsureProviderIsLoaded())
                _providerInstance.SetNamedCache(cacheName);
        }

        /// <summary>
        /// Sets the Default Named Cache if supported by the provider.  <seealso cref="IsNamedCacheSupported"/>
        /// Call this method in a finally block after the call to <see cref="SetNamedCache(string)"/> to restore
        /// the default cache.
        /// </summary>
        public static void SetDefaultCache()
        {
            if (EnsureProviderIsLoaded())
                _providerInstance.SetDefaultCache();
        }

        /// <summary>
        /// Notifies the Cache Server that this client is closing down.
        /// </summary>
        public static void NotifyCacheClientClosing()
        {
            if (EnsureProviderIsLoaded())
                _providerInstance.NotifyCacheServer(true);
        }

        /// <summary>
        /// Warms-up the Provider before usage to avoid delays during actual calls.
        /// </summary>
        /// <returns></returns>
        public static bool WarmupCacheProvider()
        {
            return EnsureProviderIsLoaded();
        }

        #endregion

    }
}
